
using System;
using System.Collections;
using UnityEngine;

//========================================================
// class BaseSingleton
//========================================================
// - for making singleton object
// - usage
//		+ declare class(derived )	
//			public class OnlyOne : BaseSingleton< OnlyOne >
//		+ client
//			OnlyOne.Instance.[method]
//========================================================
public abstract class Singleton<T> where T : new()
{
	protected static T instance;
	public static T Instance
	{
		get
		{
			if (instance == null)
			{
				instance = new T();
			}
			return instance;
		}
	}
}


/// <summary>
/// Singleton for mono behavior object, auto create gameobject if not exist => HAN CHE SU DUNG CLASS NAY
/// </summary>
/// <typeparam name="T"></typeparam>
public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour
{
	private static T singleton;
	private static object lockObj = new object();
	private static bool isDestroying = false;

	
	public static bool IsInstanceValid() { return singleton != null; }
	
	void Reset()
	{
		gameObject.name = typeof(T).Name;
	}
	
	public static T Instance
	{
		get
		{


			lock(lockObj)
			{
				if (singleton == null)
				{
					singleton = (T)FindObjectOfType(typeof(T));

					if(FindObjectsOfType(typeof(T)).Length > 0)
					{
//						Debug.LogError("Sao lai co 2 instance " + typeof(T));
						return singleton;
					} 
					if (singleton == null)
					{
						if(isDestroying)
						{
							Debug.LogError("Cannot creat destroying object " + typeof(T));
							return null;
						}

						GameObject obj = new GameObject();
						obj.name = "[@" + typeof(T).Name + "]";
						singleton = obj.AddComponent<T>();
						DontDestroyOnLoad(singleton);
					}
				}
				
				
				return singleton;
			}
		}
	}

	protected virtual void OnDestroy()
	{
		isDestroying = true;
	}
}



/// <summary>
/// Singleton for mono behavior object, only return exsited object, don't create new
/// </summary>
/// <typeparam name="T"></typeparam>
public class ManualSingletonMono<T> : MonoBehaviour where T : MonoBehaviour
{
	protected static T instance;
	public static T Instance { 
		get
		{
			if(instance == null)
				Debug.LogError("Khong tim thay Object chua mono nay. Phai add san object nay vao scene " + typeof(T));
			return instance;
		}
	}

	public static bool IsInstanceValid()
	{
		if(instance == null)
			Debug.LogError("Khong tim thay mono nay. Phai add san object nay vao scene  " + typeof(T));
		return (instance == null)? false: true;
	}

	//Tam thoi ko chep Awake tai lop con, neu muon phai virtual ham nay
	protected void Awake()
	{
		if (instance == null)
			instance = (T)(MonoBehaviour)this;

		if(instance == null)
		{
			Debug.LogError ("Awake xong van NULL " + typeof(T));
		}

	}
	
	protected virtual void OnDestroy()
	{
		//Debug.LogError ("OnDestroy " + typeof(T));
		if (instance == this)
			instance = null;
	}
}
